﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using BIG = System.Numerics.BigInteger;
using PodpisyElektorniczne.Interfaces;


namespace PodpisyElektorniczne.Classes
{
    public class UserKeys : IKeyGenerator<BIG>
    {
        private BIG X { get; set; }
        public BIG Y { get; protected set; }

        /// <summary>
        /// To Prepare and generate keys from scratch
        /// </summary>
        public UserKeys()
        {
            X = new BIG(-1);
            Y = new BIG(-1);
        }
        /// <summary>
        /// To create class instance with already generated keys
        /// </summary>
        /// <param name="x">private key</param>
        /// <param name="y">public key</param>
        public UserKeys(BIG x, BIG y)
        {
            X = x;
            Y = y;
        }

        public UserKeys(byte[] x, byte[] y)
        {
            X = new BIG(x);
            Y = new BIG(y);
        }

        public BIG GetPrivateKey()
        {
            return X;
        }
        /// <summary>
        /// Remember that X must belongo to group Z_q
        /// </summary>
        /// <param name="order"></param>
        protected void GeneratePrivateKey(BIG order)
        {
            var cp = new CspParameters();
            cp.KeyContainerName = "MyPrivKey";
            cp.KeyNumber = (int) KeyNumber.Signature;

            var rsaCsp = new RSACryptoServiceProvider(cp);
            var rsaParams = rsaCsp.ExportParameters(true);

            X =  (BIG.Abs(new BIG(rsaParams.D))) % order;
        }

        protected void GeneratePublicKey(BIG g, BIG order)
        {
            Y = BIG.ModPow(g, this.X, order);
        }

        public void GenerateKeyPair(BIG order, BIG g)
        {
            GeneratePrivateKey(order);
            GeneratePublicKey(g, order);
        }

        public override string ToString()
        {
            return string.Format("{0}{1}", X.ToString("R"), Y.ToString("R"));
        }
    }
}
